datetime的介绍


datetime 和 time 的区别: 
  • datetime 是在 time 模块的基础上封装的
  • datetime 所返回的是时间对象

注意:在本章节中虽然打印出来是一个日期字符串,但是实际上是一个日期对象,除非使用了格式化日期对象

取当前时间


1. 取当前时间

import datetime

datetime.datetime.now()  # 2019-05-02 12:30:47.928455 -> 类型: <class 'datetime.datetime'>
datetime.datetime.today()  # 2019-05-02 12:30:47.928455 -> 类型: <class 'datetime.datetime'>
datetime.date.today()  # 2019-05-02 -> 类型: <class 'datetime.date'>

指定时间的日期对象


1. 指定时间的日期对象

import datetime

datetime.datetime(year=2019, month=3, day=20, hour=10, minute=1, second=32, microsecond=1)  # 2019-03-20 10:01:32.000001 -> 类型: <class 'datetime.datetime'>
datetime.date(year=2019, month=3, day=20)  # 2019-03-20 -> 类型: <class 'datetime.date'>
datetime.time(hour=10, minute=1, second=32, microsecond=1)  # 10:01:32.000001 -> 类型: <class 'datetime.time'>

获取日期对象中的具体时间参数


1. 获取日期对象中的日期和时间(返回值: 日期对象)

  • 日期对象.date() -> 获取日期对象中的日期

# 获取日期

date = datetime.datetime.now().date() # 2019-06-11 -> 类型:<class 'datetime.date'>

date = datetime.datetime(year=2019, month=3, day=20, hour=10, minute=1, second=32, microsecond=1).date() # 2019-03-20 -> 类型:<class 'datetime.date'>

  • 日期对象.time() -> 获取日期对象中的时间

# 获取时间

date = datetime.datetime.now().time()  # 16:05:49.278866 -> 类型:<class 'datetime.time'>

date = datetime.datetime(year=2019, month=3, day=20, hour=10, minute=1, second=32, microsecond=1).time()  # 10:01:32.000001 -> 类型:类型:<class 'datetime.time'>

2. 获取日期对象中的年月日时分秒(返回值:字符串)

import datetime

# date_obj = datetime.datetime(year=2019, month=3, day=20, hour=10, minute=1, second=32, microsecond=1)
date_obj = datetime.datetime.now()
print(date_obj.year)  # 2019
print(date_obj.month)  # 5
print(date_obj.day)  # 2
print(date_obj.hour)  # 12
print(date_obj.minute)  # 58
print(date_obj.second)  # 43
print(date_obj.microsecond)  # 202714

timedelta 日期对象


1. timedelta 日期对象的介绍

  • timedelta 日期对象: 通过 日期对象之间的运算 或 .timedelta() 方法 所返回的一个对象

2. .timedelta() 方法

  • .timedelta() -> 返回一个指定天数的 timedelta 日期对象,用于日期的运算

  • .timedelta(weeks=float, days=float, hours=float, minutes=float, seconds=float, microseconds=float, milliseconds=float) 参数

    • weeks -> 指定周数
    • days -> 指定天数
    • hours -> 指定小时
    • minutes -> 指定分钟
    • seconds -> 指定秒数
    • microseconds -> 指定微秒
    • milliseconds -> 指定毫秒

import datetime

date_obj = datetime.datetime.now()  # 2019-05-02 13:32:02.220621 -> 类型: <class 'datetime.datetime'>
days = datetime.timedelta(days=7)  # 7 days, 0:00:00 -> 指定一个7天的对象 -> 类型: <class 'datetime.timedelta'>
new_date_obj = date_obj + days  # 2019-05-09 13:22:49.300992 -> 获取当前时间的7天后日期 -> 类型: <class 'datetime.datetime'>

import datetime

date_obj = datetime.datetime(year=2019, month=3, day=20, hour=10, minute=1, second=32, microsecond=1)  # 2019-03-20 10:01:32.000001 -> 类型: <class 'datetime.datetime'>
days = datetime.timedelta(days=7)  # 7 days, 0:00:00 -> 指定一个7天的对象 -> 类型: <class 'datetime.timedelta'>
new_date_obj = date_obj + days  # 2019-03-27 10:01:32.000001 -> 获取指定时间的7天后日期 -> 类型: <class 'datetime.datetime'>

3. timedelta 日期对象所提供的属性(常用的)

  • .days
    • .timedelta()返回的 timedelta 日期对象代表: 获取指定天数
    • 两个日期对象之间运算后返回的 timedelta 日期对象代表: 获取两个日期之间的天数差

  • .seconds
    • .timedelta()返回的 timedelta 日期对象代表: 获取指定秒数
    • 两个日期对象之间运算后返回的 timedelta 日期对象代表: 获取两个日期之间的秒数差,忽略微秒数,忽略天数

  • .microseconds
    • .timedelta()返回的 timedelta 日期对象代表: 获取指定微妙
    • 两个日期对象之间运算后返回的 timedelta 日期对象代表: 获取两个日期之间的微妙差


  • .timedelta()返回的 timedelta 日期对象

import datetime

timedelta_obj = datetime.timedelta(weeks=1)

d = timedelta_obj.days  # 7
s = timedelta_obj.seconds  # 0
ms = timedelta_obj.microseconds  # 0

  • 两个日期对象之间运算后返回的 timedelta 日期对象

import datetime

now = datetime.datetime.now()
previous_time = datetime.datetime(year=2019, month=3, day=20, hour=10, minute=1, second=32, microsecond=1)
time_difference = now - previous_time

d = time_difference.days  # 132
s = time_difference.seconds  # 45146
ms = time_difference.microseconds  # 591401

4. timedelta 日期对象所提供的方法(常用的)

  • .total_seconds() -> 获取两个时间之间的总差(以秒为单位)

import datetime

now = datetime.datetime.now()
previous_time = datetime.datetime(year=2019, month=3, day=20, hour=10, minute=1, second=32, microsecond=1)
time_difference = now - previous_time

ts = time_difference.total_seconds()  # 11451066.794178

计算时间差


注意: 日期对象之间的运算必须是同一个时间类型(例: datetime 必须和 datetime 进行运算,时区类型必须一致,且 datetime 不能和 date 进行运算,但是 datetime/date 可以与 timedelta 日期对象 进行运算)

1. 日期对象之间进行运算

  • 注意日期对象在进行运算后会返回一个 timedelta 日期对象 和 .timedelta() 返回的 timedelta 日期对象是一样的

import datetime

date_obj1 = datetime.datetime.now()  # 2019-05-02 13:41:15.291482 -> 类型: <class 'datetime.datetime'>
date_obj2 = datetime.datetime(year=2019, month=3, day=20, hour=10, minute=1, second=32, microsecond=1)  # 2019-03-20 10:01:32.000001 -> 类型: <class 'datetime.datetime'>
date_t = date_obj1 - date_obj2
print(date_t)  # 43 days, 3:39:43.291481 -> 类型: <class 'datetime.timedelta'>
print(date_t.days)  # 43
print(date_t.seconds)  # 13183
print(date_t.microseconds)  # 291481

  • 注意: 日期对象在进行运算后会返回一个 timedelta 日期对象 和 .timedelta() 返回的 timedelta 日期对象是一样的,所以可以和下面的.timedelta()一样对日期的运算,然后返回一个日期对象

import datetime

date_obj1 = datetime.datetime.now()  # 2019-05-02 13:39:36.784401 -> 类型: <class 'datetime.datetime'>
date_obj2 = datetime.datetime(year=2019, month=3, day=20, hour=10, minute=1, second=32, microsecond=1)  # 2019-03-20 10:01:32.000001 -> 类型: <class 'datetime.datetime'>
date_t = date_obj1 - date_obj2  # 43 days, 3:38:04.784400 -> 类型: <class 'datetime.timedelta'>
new_date_obj = datetime.datetime.now() + date_t  # 2019-06-14 17:17:41.568801 -> 类型: <class 'datetime.datetime'>

2. 日期对象 和 timedelta 日期对象 之间进行运算

  • 说明: 在原本的日期对象上增加时间或者减少时间,并且返回一个新的日期对象(非 timedelta 日期对象

  • 日期对象和timedelta 日期对象 之间进行运算会返回一个新的日期对象(非 timedelta 日期对象

import datetime

date_obj = datetime.datetime.now()  # 2019-05-02 13:32:02.220621 -> 类型: <class 'datetime.datetime'>
days = datetime.timedelta(days=7)  # 7 days, 0:00:00 -> 指定一个7天的对象 -> 类型: <class 'datetime.timedelta'>
new_date_obj = date_obj + days  # 2019-05-09 13:22:49.300992 -> 获取当前时间的7天后日期 -> 类型: <class 'datetime.datetime'>

import datetime

date_obj = datetime.datetime(year=2019, month=3, day=20, hour=10, minute=1, second=32, microsecond=1)  # 2019-03-20 10:01:32.000001 -> 类型: <class 'datetime.datetime'>
days = datetime.timedelta(days=7)  # 7 days, 0:00:00 -> 指定一个7天的对象 -> 类型: <class 'datetime.timedelta'>
new_date_obj = date_obj + days  # 2019-03-27 10:01:32.000001 -> 获取指定时间的7天后日期 -> 类型: <class 'datetime.datetime'>

3. 错误示范

  • 注意: 日期对象之间的运算必须是同一个时间类型(例: datetime 必须和 datetime 进行运算,时区类型必须一致,且 datetime 不能和 date 进行运算,但是 datetime/date 可以与 timedelta 日期对象 进行运算

  • datetime 和 date 进行运算

import datetime

now = datetime.datetime.now()
previous_time = datetime.date(year=2019, month=3, day=20)

result = now - previous_time  # datetime 类型 和 date类型 不能进行运算

  • 时区类型不一致进行运算(即: 一个日期对象有时区,一个日期对象没有时区)

import datetime
import pytz

date_obj1 = datetime.datetime.now()  # offset-naive: 不含时区
date_obj2 = datetime.datetime(year=2019, month=3, day=20, hour=10, minute=1, second=32, microsecond=1, tzinfo=pytz.timezone('UTC'))  # offset-aware: 包含时区

date_t = date_obj1 - date_obj2  # 时区类型不一致不能进行运算

日期对象之间的比较


注意: 日期对象之间的比较必须是同一个时间类型(例: datetime 必须和 datetime 进行比较,timedelta 日期对象 必须和 timedelta 日期对象 比较,时区类型必须一致,且 datetime 不能和 date 进行比较)

1. 日期对象 和 日期对象的比较

import datetime

now = datetime.datetime.now()
previous_time = datetime.datetime(year=2019, month=3, day=20, hour=10, minute=1, second=32, microsecond=1)

result = now > previous_time  # True

2. timedelta 日期对象 和 timedelta 日期对象的比较

import datetime

now = datetime.datetime.now()
previous_time = datetime.datetime(year=2019, month=3, day=20, hour=10, minute=1, second=32, microsecond=1)
time_difference = now - previous_time  # 类型: <class 'datetime.timedelta'>, 日期对象之间进行运算后返回的类型和.timedelta()返回的类型是一样
tow_week = datetime.timedelta(weeks=2)  # 类型: <class 'datetime.timedelta'>

result = time_difference > tow_week  # True

import datetime

one_day = datetime.timedelta(days=3)  # 类型: <class 'datetime.timedelta'>
tow_week = datetime.timedelta(weeks=2)  # 类型: <class 'datetime.timedelta'>

result = one_day > tow_week  # False

3. 错误示范

  • 注意: 日期对象之间的比较必须是同一个时间类型(例: datetime 必须和 datetime 进行比较,timedelta 日期对象 必须和 timedelta 日期对象 比较,时区类型必须一致,且 datetime 不能和 date 进行比较

  • datetime 和 date 进行比较

import datetime

now = datetime.datetime.now()
previous_time = datetime.date(year=2019, month=3, day=20)
result = now > previous_time  # datetime 类型 和 date类型 不能进行比较,因为日期类型不一致

  • datetime 和 timedelta 进行比较

import datetime

now = datetime.datetime.now()
two_week = datetime.timedelta(weeks=2)
result = now > two_week  # datetime 类型 和 timedelta类型 不能进行比较,因为日期类型不一致

  • 时区类型不一致进行比较(即: 一个日期对象有时区,一个日期对象没有时区)

import datetime
import pytz

date_obj1 = datetime.datetime.now()  # offset-naive: 不含时区
date_obj2 = datetime.datetime(year=2019, month=3, day=20, hour=10, minute=1, second=32, microsecond=1, tzinfo=pytz.timezone('UTC'))  # offset-aware: 包含时区

date_t = date_obj1 > date_obj2  # 时区类型不一致不能进行比较

时区类型


1.时区类型

  • offset-naive: 不含时区
  • offset-aware: 包含时区

2.查看日期对象是否包含时区

  • 日期对象.tzinfo

  • 通过 datetime 模块生成的日期对象 或 从数据库中获取到的日期对象(前提: USE_TZ = False -> [setting.py]) 都不会包含时区

import datetime
from app01.models import *

# --------------- 通过 datetime 模块生成的日期对象 -------------------

now = datetime.datetime.now()
print(now.tzinfo)  # None -> offset-naive: 不含时区

specified_date = datetime.datetime(year=2019, month=3, day=20, hour=10, minute=1, second=32, microsecond=1)
print(now.tzinfo)  # None -> offset-naive: 不含时区

# --------------- 从数据库中获取到的日期对象(前提: USE_TZ = False -> [setting.py]) -------------------

time_obj = TimeTable.objects.filter(id=1).first()
print(time_obj.time.tzinfo)  # None -> offset-naive: 不含时区

# settings.py

USE_TZ = False  # 查询出不含时区的日期对象

  • 从数据库中获取到的日期对象(前提: USE_TZ = True -> [setting.py]) 或 手动设置了时区的日期对象 都会包含时区

import datetime
import pytz
from app01.models import *

# --------------- 从数据库中获取到的日期对象(前提: USE_TZ = True -> [setting.py]) -------------------

time_obj = TimeTable.objects.filter(id=1).first()
print(time_obj.time.tzinfo)  # UTC -> offset-aware: 包含时区

# --------------- 手动设置了时区的日期对象 -------------------

now = datetime.datetime.now().replace(tzinfo=pytz.timezone('UTC'))
print(now.tzinfo)  # UTC -> offset-aware: 包含时区

specified_date = datetime.datetime(year=2019, month=3, day=20, hour=10, minute=1, second=32, microsecond=1, tzinfo=pytz.timezone('UTC'))
print(now.tzinfo)  # UTC -> offset-aware: 包含时区

# settings.py

USE_TZ = True  # 查询出包含时区的日期对象

3.修改日期对象的时区

  • 添加时区

    • 通过 pytz 模块创建某个时区对象
    • 使用 tzinfo 属性添加时区对象

import datetime
import pytz

now = datetime.datetime.now().replace(tzinfo=pytz.timezone('UTC'))
print(now.tzinfo)  # UTC -> offset-aware: 包含时区

specified_date = datetime.datetime(year=2019, month=3, day=20, hour=10, minute=1, second=32, microsecond=1, tzinfo=pytz.timezone('UTC'))
print(now.tzinfo)  # UTC -> offset-aware: 包含时区

  • 去除时区

import datetime
from app01.models import *

# ------------------------- 查询出来的日期对象 ----------------------------------

time_obj = TimeTable.objects.filter(id=1).first()
time_obj_time = time_obj.time.replace(tzinfo=None)
print(time_obj_time.tzinfo)  # None -> offset-naive: 不含时区

# ----------------- 通过 datetime 模块生成的日期对象(一般是不用去除的,因为默认就不带时区,这里只是为了演示) -----------------

now = datetime.datetime.now().replace(tzinfo=None)
print(now.tzinfo)  # None -> offset-naive: 不含时区

specified_date = datetime.datetime(year=2019, month=3, day=20, hour=10, minute=1, second=32, microsecond=1, tzinfo=None)
print(now.tzinfo)  # None -> offset-naive: 不含时区

4.在日常开发中要注意获取到的时间是否相差 8 小时

5.在 Django 开发中 日期的运算 和 比较 都需要注意时区类型

  • 不同时区的类型的运算和比较错误提醒(即: 一个日期对象有时区,一个日期对象没有时区)


Traceback (most recent call last):
  File "C:/Users/Mr. Yeung/Desktop/PyFolder/test_time/app01/tests.py", line 27, in <module>
    print(time_obj.time - now)
TypeError: can't subtract offset-naive and offset-aware datetimes

  • 解决办法 -> 统一时间类型

    • 统一为 offset-naive: 不含时区

      • 方法一 -> 将查询到的日期对象变成不包含时区的日期对象

import datetime
from app01.models import *

time_obj = TimeTable.objects.filter(id=1).first()
time_obj_time = time_obj.time.replace(tzinfo=None)  # 将查询到的日期对象变成不包含时区的日期对象
print(time_obj_time.tzinfo)  # None -> offset-naive: 不含时区

now = datetime.datetime.now()
print(now.tzinfo)  # None -> offset-naive: 不含时区

difference_time = now - time_obj_time  # 10:46:45.613783
result = now > time_obj_time  # True

      • 方法二 -> 在 settings.py 中设置 USE_TZ = False,那么直接查询到的是不带时区的日期对象

# settings.py

USE_TZ = False

import datetime
from app01.models import *

time_obj = TimeTable.objects.filter(id=1).first()
print(time_obj.time.tzinfo)  # None -> offset-naive: 不含时区

now = datetime.datetime.now()
print(now.tzinfo)  # None -> offset-naive: 不含时区

difference_time = now - time_obj.time  # 10:51:10.098679
result = now > time_obj.time  # True

    • 统一为 offset-aware: 包含时区

      • 前提: settings.py 中的设置 USE_TZ = True

# settings.py

USE_TZ = True

import datetime
import pytz
from app01.models import *

time_obj = TimeTable.objects.filter(id=1).first()
print(time_obj.time.tzinfo)  # UTC -> offset-aware: 包含时区

now = datetime.datetime.now().replace(tzinfo=pytz.timezone('UTC'))
print(now.tzinfo)  # UTC -> offset-aware: 包含时区

difference_time = now - time_obj.time  # 10:55:30.414490
result = now > time_obj.time  # True

将时间戳装换为日期对象


1. 将时间戳转换为日期对象

import datetime
import time

datetime.datetime.fromtimestamp(time.time())  # 2019-05-02 13:51:45.994251 -> 类型: <class 'datetime.datetime'>
datetime.date.fromtimestamp(time.time())  # 2019-05-02 -> 类型: <class 'datetime.datetime'>

# 对时间戳转换为日期对象后进行格式化
datetime.datetime.fromtimestamp(time.time()).strftime('%Y/%m/%d %H:%M:%S')  # 2019/05/02 13:51:45 -> 类型: <class 'str'>
datetime.date.fromtimestamp(time.time()).strftime('%Y/%m/%d')  # 2019/05/02 -> 类型: <class 'str'>

格式化日期对象


1. 格式化日期对象

  • 通俗理解: 将日期对象装换为指定格式的日期字符串

import datetime

datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S')  # 2019/05/02 13:59:38 -> 类型: <class 'str'>
datetime.datetime.now().strftime('%H:%M:%S')  # 14:00:51 -> 类型: <class 'str'>
datetime.datetime(year=2019, month=3, day=20, hour=10, minute=1, second=32, microsecond=1).strftime('%Y/%m/%d %H:%M:%S')  # 2019/03/20 10:01:32 -> 类型: <class 'str'>
datetime.date(year=2019, month=3, day=20).strftime('%Y/%m/%d')  # 2019/03/20 -> 类型: <class 'str'>

将字符串转换成日期对象


1. 将字符串转换成日期对象

import datetime

datetime.datetime.strptime('2017-8-1 18:20:20', '%Y-%m-%d %H:%M:%S')  # 2017-08-01 18:20:20 -> 类型: <class 'datetime.datetime'>
datetime.datetime.strptime('2017-8-1', '%Y-%m-%d')  # 2017-08-01 00:00:00 -> 类型: <class 'datetime.datetime'>